<?php

class My_Db_Table extends Zend_Db_Table_Abstract {

    const DATE_PATTERN = 'Y-m-d';
    const TIME_PATTERN = 'H:i:s';
    const DATE_TIME_PATTERN = 'Y-m-d H:i:s';

    /**
     *
     * @var Zend_Translate
     */
    protected static $translator = null;

    protected static function translate($key) {
        if (self::$translator == null) {
            self::$translator = Zend_Registry::get('Zend_Translate');
        }
        $arg_list = func_get_args();
        $msg = self::$translator->_($key);
        if (count($arg_list) > 1) {
            array_splice($arg_list, 0, 1);
            $msg = sprintf($msg, $arg_list[0]);
        }
        return $msg;
    }

    protected function _($key) {
        return self::translate($key);
    }

    protected function getMainCodeColumnName() {
        return 'code';
    }

    public function createNewCode($len = 10, $charUniverse = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') {
        $randomString = '';
        $universeSize = strlen($charUniverse) - 1;
        for ($i = 0; $i < $len; $i++) {
            $randInt = mt_rand(0, $universeSize);
            $randChar = $charUniverse[$randInt];
            $randomString .= $randChar;
        }
        return $randomString;
    }

    protected function insertWithCode(array $data) {
        $codeColumn = $this->getMainCodeColumnName();
        if ($codeColumn == null || empty($codeColumn)) {
            return parent::insert($data);
        }
        do {
            $codeVal = $this->createNewCode();
            $r = $this->select(self::SELECT_WITH_FROM_PART)
                    ->where($codeColumn . ' = ?', $codeVal)
                    ->query()->fetch();
            if(empty($r)) {
                break;
            }
        } while (true);
        $data[$codeColumn] = $codeVal;
        $rowId = parent::insert($data);
        if (!$rowId) {
            throw new My_Exception('Unable to get a row ID while inserting data to ' . $this->_name);
        }
        return $rowId;
    }

    public function select($withFromPart = self::SELECT_WITHOUT_FROM_PART) {
        return parent::select($withFromPart)->setIntegrityCheck(false);
    }

    public function get($id) {
        $str = $this->getPrimary() . ' = ?';
        return $this->select()->where($str, $id)->query()->fetch();
    }

    public function getByColumn($val, $columnName) {
        if (!empty($columnName) && is_string($columnName)) {
            return $this->select()->where($columnName . ' = ?', $val)->query()->fetch();
        }
        throw new My_Exception('No code column definied for ' . $this->_name);
    }

    public function getByCode($code) {
        $codeColumnName = $this->getMainCodeColumnName();
        return $this->getByColumn($code, $codeColumnName);
    }

    public function getPrimary() {
        if (is_array($this->_primary)) {
            foreach ($this->_primary as $primary) {
                return $primary;
            }
        }
        return $this->_primary;
    }

    public function insert(array $data) {
        $defaults = $this->getDefaultRowValues();
        if ($defaults != null && !empty($defaults)) {
            $data = array_merge($defaults, $data);
        }
        if (!isset($data['creation_date'])) {
            $data['creation_date'] = date(self::DATE_TIME_PATTERN);
            $data['modification_date'] = $data['creation_date'];
        }
        if (!isset($data['created_by'])) {
            if (Zend_Auth::getInstance()->hasIdentity()) {
                $data['created_by'] = Zend_Auth::getInstance()->getIdentity()->user_id;
            } else {
                $data['created_by'] = 0;
            }
        }
        $data['modified_by'] = $data['created_by'];
        return $this->insertWithCode($data);
    }

    public function update(array $data, $whereOrId, $whereColumn = null) {
        if (!isset($data['modification_date'])) {
            $data['modification_date'] = date(self::DATE_TIME_PATTERN);
        }
        if (!isset($data['modified_by'])) {
            if (Zend_Auth::getInstance()->hasIdentity()) {
                $data['modified_by'] = Zend_Auth::getInstance()->getIdentity()->user_id;
            } else {
                $data['modified_by'] = 0;
            }
        }
        if ($whereColumn != null) {
            $whereOrId = $this->getAdapter()->quoteInto($whereColumn . ' = ?', $whereOrId);
        } elseif (is_numeric($whereOrId)) {
            $id = $whereOrId;
            $primary = $this->getPrimary();
            $whereOrId = $this->getAdapter()->quoteInto($primary . ' = ?', $id);
        }
        return parent::update($data, $whereOrId);
    }

    public function delete($whereOrId, $whereColumn = null) {
        if ($whereColumn != null) {
            $whereOrId = $this->getAdapter()->quoteInto($whereColumn . ' = ?', $whereOrId);
        } elseif (is_numeric($whereOrId)) {
            $id = $whereOrId;
            $primary = $this->getPrimary();
            $whereOrId = $this->getAdapter()->quoteInto($primary . ' = ?', $id);
        }
        return parent::delete($whereOrId);
    }

    public function getDefaultRowValues() {
        return array();
    }

}

